var HooFlyMenu = new Class({
   options: {
    onBeforeShow: function() {return true}, //true or false
    onBeforeHide: function() {return true}, //true or false
    position: 'inside', //'mouse', 'inside', 'outside', 'absolute'
    direction: 'top-left', //'top-left', 'top-right', 'bottom-left', 'bottom-right' //TODO 'auto'
    offset: {x:0,y:0},
    durationShow: 2000,
    durationSwitch: 300,
    durationHide: 1000
   },

   initialize: function (element, options) {
    this.element = element;
    this.element._HooFlyMenu = this;
    this.element._HooFlyMenuSelf = true;
    this.element.setStyles({
	display: 'none',
	position: 'absolute',
	'z-index': 99
    });
    this._visible = false;
    if ($defined(options)) this.options = $merge(this.options, options);
    this.element.addEvent('mouseover', this.onOver);
    this.element.addEvent('mouseout', this.onOut);
   },

   show: function (newelement, options) {
       //return false;
       this._showOn = false;
       var element = $defined(newelement)?newelement:this._parent;
      // alert(this._parent);
	if (!$defined(element)) return false;
	if (!this._inside) return false;
	//if (this._visible && (element._HooFlyMenuSelf || (element == this._parent))) return false;
	if (!element._HooFlyMenuSelf) this._parent = element;
	var opts = this.options;
	if ($defined(element._HooFlyMenuOptions)) {opts = $merge(opts, element._HooFlyMenuOptions);}
	this.element.setStyle('display', '');
	if (opts.onBeforeShow(element, opts, this)) {
	    var x = 0; var y = 0;
	    var pcoords = element.getCoordinates();
	    var esize = this.element.getSize();
	    switch (opts.position) {
	    case 'absolute':
		x = opts.coords.x;
		y = opts.coords.y;
		break;
	    case 'outside':
		switch (opts.direction) {
		case 'bottom-left':
		case 'bottom-right':
		    y = pcoords.top + pcoords.height;
		    break;
		default:
		    y = pcoords.top;
		}

		switch (opts.direction) {
		case 'top-right':
		case 'bottom-right':
		    x = pcoords.left + pcoords.width - esize.x;
		    break;
		default:
		    x = pcoords.left - esize.x;
		}
		break;
	    case 'mouse':
		//TODO: make mouse position detection
	    default: //inside
		switch (opts.direction) {
		case 'bottom-left':
		case 'bottom-right':
		    y = pcoords.top + pcoords.height - esize.y;
		    break;
		default:
		    y = pcoords.top;
		}

		switch (opts.direction) {
		case 'top-right':
		case 'bottom-right':
		    x = pcoords.left + pcoords.width - esize.x;
		    break;
		default:
		    x = pcoords.left;
		}
	    }
	    this.element.setStyles({left: x + opts.offset.x, top: y + opts.offset.y});
	    this._parent = element;
	    this._visible = true;
	    return true;
	}
	return false;
    },

   hide: function (hidenow) {
        // return false;
	this._hideOn = false;
	if (this._inside && !hidenow) return false;
	if (!this._visible) return false;
	var opts = this.options;
	if (this.options.onBeforeHide(element, opts, this)) {
	    //this._parent = undefined;
	    this.element.setStyle('display', 'none');
	    this._visible = false;
	    return true;
	}
	return false;
	//this.
   },

   onOut: function () {
	if (!this._HooFlyMenu) return;
	var menu = this._HooFlyMenu;
	if (!menu._inside) return;
	menu._inside = false;
	if (!menu._visible) return;
	//$clear(menu.show);
	//$clear(menu.hide);
	//this._showOn = false;

	if (!menu._hideOn) {
	    menu.hide.delay(menu.options.durationHide, menu);
	    menu._hideOn = true; //this._showOn = false;
	}
   },

   onOver: function () {
	if (!this._HooFlyMenu) return;
	var menu = this._HooFlyMenu;
	if (menu._inside && (this == menu._parent)) return;
	if (menu._visible && (this._HooFlyMenuSelf || (this == menu._parent))) {
	    menu._inside = true;
	    return;
	}
	//$clear(menu.hide);
	//$clear(menu.show);
	//
	if (!this._HooFlyMenuSelf) menu._parent = this;
	menu._inside = true;
	if (!menu._showOn) {
	    menu.show.delay(menu._visible?menu.options.durationSwitch:menu.options.durationShow, menu);
	    menu._showOn = true;
	}
   },

   onClick: function () {
	if (!this._HooFlyMenu) return;
	var menu = this._HooFlyMenu;
	if (!menu._visible || !(this == menu._parent)) {
	    menu._inside = true;
	    menu.show(this);
	    menu._showOn = true;
	} else {
	    menu._inside = false;
	    menu.hide(true);
	    menu._hideOn = true;
	}
   },

   bindElement: function (element, options) {
	element._HooFlyMenu = this;
	var events = {over: true, click: false};
	if ($defined(options)) {
	    if ($defined(options.events)) {
		events = $merge(events, options.events);
		delete(options.events);
	    }
	    element._HooFlyMenuOptions = options;
	}
	if (events.over) {
	    element.addEvent('mouseover', this.onOver);
	    element.addEvent('mouseout', this.onOut);
	}
	if (events.click) element.addEvent('click', this.onClick);
   }
});